package edu.ccut.titan.tag.report.servlet;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.base.JRBaseReport;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.j2ee.servlets.ImageServlet;
import edu.ccut.titan.component.TitanDataSource;
import edu.ccut.titan.tag.report.chart.IType;
import edu.ccut.titan.tag.report.chart.Type;
import edu.ccut.titan.tag.report.design.ReportDesignInfo;

public class ReportServlet extends HttpServlet implements IReport {

	public static final String LEFTMARGIN = "leftmargin";
	public static final String TOPMARGIN = "topmargin";
	public static final String PAGEINDEX = "page";

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		JasperPrint print = this.getJasperPrint(request, response);

		if (print != null) {
			this.printReport(print, request, response);
		}
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}

	@SuppressWarnings("unchecked")
	private JasperPrint getJasperPrint(HttpServletRequest request,
			HttpServletResponse response) {
		JasperPrint print = null;
		JasperReport jasperReport = null;
		try {
			jasperReport = this.getJasperReport(request);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			this.configMargin(jasperReport, request);
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		TitanDataSource datasource = new TitanDataSource();
		String reload = request.getParameter(RELOAD);
		ReportDesignInfo config = null;
		if (!"true".equalsIgnoreCase(reload)) {
			datasource.setTitanData((List<Map<String, Object>>) request
					.getAttribute(SOURCE));
		} else {
			datasource.setTitanData((List<Map<String, Object>>) request
					.getSession().getAttribute(SOURCE));
		}

		try {
			print = JasperFillManager.fillReport(jasperReport,
					getReportParameter(request), datasource);
		} catch (JRException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		removeBlankPage(print);
		request.getSession().setAttribute(PRINT, print);
		request.setAttribute(PRINT, print);
		
		return print;
	}
	
	@SuppressWarnings("unchecked")
	private void removeBlankPage(JasperPrint print) {
		List<JRPrintPage> pages = print.getPages();
		JRPrintPage lastPage = null;
		
		if (pages != null && !pages.isEmpty()) {
			int index = pages.size() - 1;
			lastPage = pages.get(pages.size() - 1);
			
			List elements = lastPage.getElements();
			if (elements != null && elements.isEmpty()) {
				print.removePage(index);
			}
		}
	}

	@SuppressWarnings("unchecked")
	private JasperReport getJasperReport(HttpServletRequest request)
			throws IOException {
		ServletContext context = this.getServletConfig().getServletContext();
		IType type = new Type();
		JasperReport jasperReport = null;
		String reload = request.getParameter(RELOAD);
		JasperPrint print = null;
		ReportDesignInfo config = null;
		if (!"true".equalsIgnoreCase(reload)) {
			config = (ReportDesignInfo) request.getAttribute(DYNAMIC_DESIGN);
		} else {
			config = (ReportDesignInfo) request.getSession().getAttribute(
					DYNAMIC_DESIGN);
		}

		if (config != null) {
			int pageHeight = 0;
			int pageWidth = 0;
			if ("excel".equals(request.getParameter("reportType"))) {
				//if (request.getParameter("format") != null) {
				//	pageHeight = PageSize.A1.x;
				//	pageWidth = PageSize.A1.y;
				//} else {
				//	pageHeight = PageSize.A1.y;
				//	pageWidth = PageSize.A1.x;
				//}
				
				pageHeight = 10000;
				pageWidth = 10000;
			} else {
				if (request.getParameter("format") != null) {
					
					if (!"portait".equals(request.getParameter("direction"))) {
						pageHeight = type.getPageSize(request
								.getParameter("format")).y;
						pageWidth = type.getPageSize(request
								.getParameter("format")).x;
					} else {
						pageWidth = type.getPageSize(request
								.getParameter("format")).y;
						pageHeight = type.getPageSize(request
								.getParameter("format")).x;
					}
				} else {
					pageHeight = PageSize.A4.y;
					pageWidth = PageSize.A4.x;
				}
			}
			JasperDesign jasperDesign = TitanReportDesigner.getInstance()
					.getReportDesign(config,
							(String) request.getAttribute(TEMPLETE_PATH),
							pageWidth, request.getParameter("reportType"));
			request.getSession().setAttribute("format",
					request.getParameter("format"));
			request.getSession().setAttribute("direction",
					request.getParameter("direction"));

			jasperDesign.setPageHeight(pageHeight);
			jasperDesign.setColumnWidth(pageWidth - 100);
			jasperDesign.setPageWidth(pageWidth);
			try {
				jasperReport = JasperCompileManager.compileReport(jasperDesign);
			} catch (JRException e) {
				e.printStackTrace();
			}
		} else {
			String templetePath = null;
			try {
				templetePath = (String) request.getAttribute(TEMPLETE_PATH);
				JasperCompileManager.compileReportToFile(context
						.getRealPath(templetePath));
			} catch (JRException e) {
				e.printStackTrace();
			}
			String templeteJasper = "/"
					+ templetePath.replace(".jrxml", ".jasper");
			File reportFile = new File(context.getRealPath(templeteJasper));
			if (!reportFile.exists())
				throw new JRRuntimeException(
						"File /"
								+ templetePath.replace(".jrxml", "")
								+ ".jasper not found. The report design must be compiled first.");
			try {
				jasperReport = (JasperReport) JRLoader.loadObject(reportFile
						.getPath());
			} catch (JRException e) {
				e.printStackTrace();
			}
		}
		return jasperReport;
	}

	private void printReport(JasperPrint print, HttpServletRequest request,
			HttpServletResponse response) {
		String type = request.getParameter(TYPE);
		if (type == null || "".equals(type.trim())) {
			type = (String) request.getAttribute(TYPE);
		}

		request.getSession().setAttribute(
				ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, print);
		IReportExporter exporter = ReportExporterFactory
				.getReportExporter(type);

		if (exporter != null) {
			exporter.export(print, request, response);
		} else {
			ReportExporterFactory.getDefaultReportExporter().export(print,
					request, response);
		}
	}

	@SuppressWarnings("unchecked")
	private Map<String, Object> getReportParameter(HttpServletRequest request) {
		Object object = request.getAttribute(PARAMETER);

		if (object != null && object instanceof Map) {
			return (Map<String, Object>) object;
		}
		return null;
	}

	private void configMargin(JasperReport jasperReport,
			HttpServletRequest request) throws NoSuchFieldException,
			IllegalAccessException {

		String leftmargin = request.getParameter(LEFTMARGIN);
		String topmargin = request.getParameter(TOPMARGIN);

		Field margin = null;

		if (leftmargin != null && !"".equals(leftmargin)) {
			margin = JRBaseReport.class.getDeclaredField("leftMargin");
			margin.setAccessible(true);
			margin.setInt(jasperReport, Integer.valueOf(leftmargin));
		}
		if (topmargin != null && !"".equals(topmargin)) {
			margin = JRBaseReport.class.getDeclaredField("topMargin");
			margin.setAccessible(true);
			margin.setInt(jasperReport, Integer.valueOf(topmargin));
		}
	}

	public static void main(String[] args) {
		System.out.println(PageSize.getInstance().getPageSize("A4").x);
		System.out.println(PageSize.getInstance().getPageSize("A4").y);
		System.out.println(JRHtmlExporterParameter.SIZE_UNIT);
		System.out
				.println(JRHtmlExporterParameter.PROPERTY_FRAMES_AS_NESTED_TABLES);
		System.out
				.println(JRHtmlExporterParameter.PROPERTY_REMOVE_EMPTY_SPACE_BETWEEN_ROWS);
		System.out
				.println(JRHtmlExporterParameter.PROPERTY_USING_IMAGES_TO_ALIGN);

	}
}